/**
 * @author yzhou2
 */
/*
 *data={id:'-1',txt:'Root',hide:false,children:[{
    id:'1',
    txt:'child1'
 },{
 }]}} 
 **/

if (!Util) {
    var Util = {};
}
Util.TreeView = function(container,data,callback,config){
	this.autoId=0;
	this.nodes={};
	this.idMap={};
	this.container=container;
	//this.data=data||{};
	this.config={
		width:300,
		hideRoot:true,
	    dragDropable: false,
		lineable: false		
	};
	if (config) {
		$.extend(this.config, config);
	}
	this.config.dragDropable=false;
	this.callback={
		onExpand:null,//function(node)
        onCollapse:null,//function(node)
		onClick:null,//function(e,node){},
        ondblClick:null,//function(e,node){},
        onContextmenu:null//function(e,node){}
	};
	if(callback){
		$.extend(this.callback, callback);
	}
	this.el=null;
	this.dom=null;
	this.dropTip=null;
	this.nodes={};	
	this.selectedNode=null;
	this.init(data||{});
};
Util.TreeView.prototype={
	init:function(data){
	   this.dom=document.createElement('ul');
	   this.dom.className='rtq-tree';
	   this.dom.style.width=this.config.width+'px';
	   this._createTree(data);
	   this.el=$(this.dom).appendTo(this.container);     
	   if(this.config.dragDropable){
	   	   this.dropTip=$('<div class="drop-tip"></div>').appendTo(this.el);
	   }
	},
	selectNode:function(node){
		if(this.selectedNode){
			if(this.selectedNode!=node){
				this.selectedNode.txtEl.removeClass('selectNode');
				this.selectedNode=node;
                node.txtEl.addClass('selectNode');				
			}
		}else{
			this.selectedNode=node;
            node.txtEl.addClass('selectNode');
		}		
	},
	_initEvent:function(node){
		var self=this;
		node.txtEl.unbind('.treeNode');
        node.txtEl.bind('click.treeNode',function(e){
			e.stopPropagation();
            e.stopImmediatePropagation(); 
			self.selectNode(node);
            if (node.clickTimeOutObj != null) {
                clearTimeout(node.clickTimeOutObj);
            }
			if (typeof self.callback.ondblClick == 'function') {
				node.clickTimeOutObj = setTimeout(function(){
					node.onClickEvent();
				}, 200);
			}else{
				node.onClickEvent();
			}
        }).bind('dblclick.treeNode',function(e){
			e.stopPropagation();
            e.stopImmediatePropagation(); 
			self.selectNode(node);
            if (node.clickTimeOutObj != null) {
                clearTimeout(node.clickTimeOutObj);
            }
            node.ondblclickEvent();
        }).bind('contextmenu.treeNode',function(e){
			e.stopPropagation();
            e.stopImmediatePropagation();
			self.selectNode(node);
            node.onConetextmenuEvent(e);       
        });
		this._initDragDrop(node);
	},
	_initDragDrop:function(node){
		var self=this;
		if (this.config.dragDropable) {
            var drag = new Util.Dragable(node.txtDom, {
                onDragStart: function(e, proxy){
                    proxy.html(node.txt);
                    proxy.dragingNode=node;
                }, 
                onDrag: function(e, proxy){
					 if (proxy.droppingNode) {
					 	var offset = proxy.droppingNode.el.offset();
					 	var height = proxy.droppingNode.el.height();
						var padding = parseInt(proxy.droppingNode.el.css('paddingLeft'));
						if (e.clientY <= offset.top + height / 2) {
							self.dropTip.css({
								top: offset.top - self.dropTip.height() / 2,
								left: offset.left + padding,
								display: 'block'
							});
						}else {
							self.dropTip.css({
								top: offset.top +height+ self.dropTip.height() / 2,
								left: offset.left + padding,
								display: 'block'
							});
						}
					 }
                }
            },
            {
                group: 'QS_TREE',
                autoProxy:true,
                delay:30
            });
            var drop = new Util.Dropable(node.txtDom, {
               onEnter: function(e, proxy){
                   proxy.droppingNode = node;
               },
               onDrop: function(e, proxy){
			       //console.log(proxy.dragingNode); 
	               //console.log(proxy.droppingNode); 
				   if (proxy.dragingNode != node && proxy.droppingNode) {
					  
					 
				   }
				   self.dropTip.hide();
				   proxy.droppingNode = null;
               },
               onOut: function(e, proxy){
			   	   self.dropTip.hide();
			   	   proxy.droppingNode = null;
               }
            },
            {
                group: 'QS_TREE'
            });
        }
	},
    _createTree:function(data){
	   this._createRoot(data);
	   if (data.children&&data.children.length>0) {
	   	   this._createChildNodes(data.children, this.root);
	   }
	},
	_createRoot:function(data){
		this.root = new Util.TreeNode(data,{
			_id:this._idService(),
			showChild:data.showChild,
			hasChild:data.children && data.children.length > 0?true:false,
			isRoot:true,
			isHide:this.config.hideRoot,
			lineable:this.config.lineable
        },this.callback);
		this.nodes[this.root._id]=this.root;
		this.idMap[data.val]=this.root._id;
		this.dom.appendChild(this.root.dom);
		this._initEvent(this.root);
	},
	_createChildNodes:function(data,pNode){
		var node=null,id,frag=document.createDocumentFragment();
		for(var i=0,l=data.length;i<l;i++){
			node = new Util.TreeNode(data[i],{
                _pId: pNode._id,
				_id: pNode._id+'_'+this._idService(),
				showChild:data[i].showChild,
				hasChild:data[i].children && data[i].children.length > 0?true:false,
				//dragDropable:this.config.dragDropable,
                lineable:this.config.lineable
            },this.callback);
			if (node.hasChild) {
				this._createChildNodes(data[i].children,node); 
			}
            pNode.setChildNode(node);
			this.nodes[node._id]=node;
			this.idMap[data[i].val]=node._id;
			frag.appendChild(node.dom);		
			//this._initDragDrop(node);	
			this._initEvent(node);
		}
		if (pNode.hasChild) {
			pNode.innerDom.appendChild(frag);
		}else{
			pNode.dom.appendChild(frag);
		}
	},
	_idService:function(){
		return this.autoId++;
	},
	getTreeData:function(node){
		var data={};
		if(!node){
			node=this.root;
		}
		data=node.data;
		if(node.childNodeIds&&node.childNodeIds.length){
			data.children=node.data.children;
			for(var i=0,l=node.childNodeIds.length;i<l;i++){
	            this.getTreeData(this._getNode(node.childNodeIds[i]));
	        }			
		}	
		return data;	
	},
	rebind:function(data){
		data=data||{};
		this._clearTreeNodes();
		this._createTree(data);
	},
	addNode:function(data,isTop,pNode){
		isTop===true?true:false;
		if(!pNode){
			pNode=this.root;
		}
		var node=new Util.TreeNode(data,{
			_pId:pNode._id,
			_id:pNode._id+"_"+this._idService(),
			showChild:data.showChild,
			hasChild:data.children && data.children.length > 0?true:false,
            //dragDropable:this.config.dragDropable,
            lineable:this.config.lineable
		},this.callback);
        pNode.setChildNode(node,true,isTop);    
		this.nodes[node._id]=node;
		this.idMap[data.val]=node._id;
		//this._initDragDrop(node);
		this._initEvent(node);
		if(node.hasChild){
			this._createChildNodes(data.children,node);
		}
	},
	removeNodeByValue:function(val){
		if (!val || !this.idMap[val]) {
		     return;
		}
		this._removeNode(this.idMap[val]);
	},
	_removeNode:function(ids){
		if(typeof ids=='string'){
			ids=[ids];
		}
		var _id;
		for(var i=0,l=ids.length;i<l;i++){
			_id=ids[i];
			if(!this.nodes[_id]){
	            continue;
	        }
	        if (this.nodes[_id].hasChild) {
				this._removeNode(this.nodes[_id].getChildNodeIds());
	        }
			if(this.selectedNode==this.nodes[_id]){
				this.selectedNode=null;
			}
			var pNode=this.nodes[this.nodes[_id]._pId];
			pNode.removeChildNode(_id,this.nodes[_id].data.val)
			this.idMap[this.nodes[_id].data.val]=null;
			delete this.idMap[this.nodes[_id].data.val];
            this.nodes[_id].clear();	
			this.nodes[_id] = null;		
            delete this.nodes[_id];				        
		}		
		
	},
	getNodeByValue:function(val){
		if (val&&this.idMap[val]) {
			return this._getNode(this.idMap[val]);
		}
		return null;
	},
	_getNode:function(id){
		if(id&&this.nodes[id]){
			return this.nodes[id];
		}
		return null;
	},
	editNode:function(node){
		
	},
	_clearTreeNodes:function(){
		for(var id in this.nodes){
            this.nodes[id].clear();
        }
		this.nodes={};
		this.idMap={};
	},
	expandAll:function(isExpand){
		for(var id in this.nodes){
			if(this.nodes[id].hasChild&&this.nodes[id]!=this.root){
				this.nodes[id].expand(isExpand);
			}
		}
	},
	clear:function(){
		this._clearTreeNodes();
	   	for(var p in this){
            if(!p || p == 'clear'){continue;}
            this[p] = null;
            delete this[p];
        }
	}
};
Util.TreeNode = function(data,config,callback){
	this.dom=null;
	this.innerDom=null;
	this.el=null;	
	this.innerEl=null;	
    this.txtEl=null;
	this.config={
		txt:'Node',
		isHide:false,
		isRoot:false,
		//dragDropable:false,
		hasChild:false,
		showChild:true,
		autoExpand:true	
	};
	if(config){
		$.extend(this.config,config);
	}
	this._id=config._id;
    this._pId=config._pId;
	this.hasChild=config.hasChild;
	this.showChild=config.showChild===false?false:true;
	this.data=data||{};//data in node
	this.txt=data.txt||config.txt;
	this.autoExpand=data.autoExpand===false?data.autoExpand:this.config.autoExpand;
	this.className=data.className||'';
	this.isHide=config.isHide;
	this.callback={
		onExpand:null,//function(node)
		onCollapse:null,//function(node)
		onClick:null,//function(e,node){},
		ondblClick:null,//function(e,node){},
	    onContextmenu:null//function(e,node){}
	};
	if(callback){
		$.extend(this.callback,callback);
	}
	this.isExpand=true;
	this.childNodeIds=null;	
	this.clickTimeOutObj=null;
	this.init();
};
Util.TreeNode.prototype = {
	init:function(){
		var self=this;
		this.dom=document.createElement('li');
		this.dom.className='expand';
		if(this.className!=''){
			this.dom.className+=' '+this.className;
		}
		if(this.config.lineable){
			this.dom.className+=' yline';
        }
		
		this.dom.pId = this._pId;
		this.dom.sId = this._id;
	
		this.txtDom=document.createElement('a');
		this.txtDom.className='node';
		if(this.config.isRoot){
            this.txtDom.className+=' root';
        }
		this.txtDom.innerHTML=this.txt;
			
		this.dom.appendChild(this.txtDom);
		
		if(this.hasChild){
			this.childNodeIds=[];
			if (!this.config.isRoot) {
				this.txtDom.className += ' folder';
			}
			this.innerDom=document.createElement('ul');
			this.innerEl=$(this.innerDom);
			this.dom.appendChild(this.innerDom);
		}else{
			this.txtDom.className+=' file';
		}		
		
		if(this.isHide){
			this.txtDom.style.display='none';
		}
		this.el=$(this.dom);
		this.txtEl=$(this.txtDom);
        if(!this.showChild||(!this.autoExpand&&this.hasChild)){
			this.expand(false);
		}
		//this._bindEvent();
	},
	expand:function(expand,isExec){
		if(expand){
			this.isExpand=true;
			this.innerEl.removeClass("collapse-ul").addClass("expand-ul");
			this.el.removeClass('collapse').addClass('expand');
			if (this.config.lineable) {
			   this.el.addClass('yline');
			}
			if (typeof this.callback.onExpand == 'function'&&isExec) {
                this.callback.onExpand(this);
            }
		}else{
			this.isExpand=false;
			this.el.removeClass('expand').addClass('collapse');
			if (this.config.lineable) {
               this.el.addClass('yline');
            }
            this.innerEl.removeClass("expand-ul").addClass("collapse-ul");
			if (typeof this.callback.onCollapse == 'function'&&isExec) {
                this.callback.onCollapse(this);
            }
		}
	},
	onClickEvent:function(){
		var self=this;       
        if (self.hasChild&&self.showChild){
            self.expand(!self.isExpand,true);
        }else{
            if (typeof self.callback.onClick == 'function') {
                self.callback.onClick(self);
            }
        }
	},
	ondblclickEvent:function(){
		var self=this;;
        if (self.hasChild&&self.showChild) {
            self.expand(!self.isExpand,true);
        }else {
            if (typeof self.callback.ondblClick == 'function') {
                self.callback.ondblClick(self);
            }
        }
	},
	onConetextmenuEvent:function(e){
		var self=this;
        if (typeof self.callback.onContextmenu == 'function') {
            self.callback.onContextmenu(e, self);
        }    
	},
//	_bindEvent:function(){
//		var self=this;
//		this.txtEl.unbind('.treeNode');
//		this.txtEl.bind('click.treeNode',function(e){
//			e.stopPropagation();
//            e.stopImmediatePropagation(); 
//			if (this.clickTimeOutObj != null) {
//				clearTimeout(this.clickTimeOutObj);
//			}
//			this.clickTimeOutObj=setTimeout(function(){
//	            self.onClickEvent();
//			},200);
//        }).bind('dblclick.treeNode',function(e){
//			e.stopPropagation();
//            e.stopImmediatePropagation(); 
//			if (this.clickTimeOutObj != null) {
//                clearTimeout(this.clickTimeOutObj);
//            }
//			self.ondblclickEvent();
//		}).bind('contextmenu.treeNode',function(e){
//			e.stopPropagation();
//            e.stopImmediatePropagation(); 
//            self.onConetextmenuEvent(e);       
//        });
//	},
	_inArray:function(a,array){
        var ret=-1;
        for(var i=0,l=array.length;i<l;i++){
            if(a==array[i]){
                ret=i;
                break;
            }
        }
        return ret;
    },
	setText:function(txt){
		this.txt=txt;
		this.txtDom.innerHTML=txt;
	},
	getId:function(id){
		return this._id;
	},
	getParentNodeId:function(){
		return this._pId;
	},
	setChildNode:function(node,isInsert,isTop){
		if(this.childNodeIds==null){
            this.childNodeIds=[];
        }
		if (isTop) {
            this.childNodeIds.unshift(node._id);
        }else{
            this.childNodeIds.push(node._id);
        }
		if(isInsert){
			if (!this.hasChild){
	            this.innerDom=document.createElement('ul');
	            this.txtDom.className='node folder';
	            this.dom.appendChild(this.innerDom); 
	            this.data.children=[];  
	            this.hasChild=true;                     
	        }
			if (isTop) {
				this.data.children.unshift(node.data);
				this.innerDom.insertBefore(node.dom, this.innerDom.firstChild);
			}else{
				this.data.children.push(node.data);
                this.innerDom.appendChild(node.dom);
			}
		}
	},
	setChildNodeIds:function(id,isTop){
		if(this.childNodeIds==null){
			this.childNodeIds=[];
		}
		if (isTop) {
			this.childNodeIds.unshift(id);
		}else{
			this.childNodeIds.push(id);
		}
	},
	getChildNodeIds:function(){
		return this.childNodeIds;
	},
	removeChildNode:function(_id,val){
		if(this.childNodeIds==null){
            return;
        }
        var idx=this._inArray(_id,this.childNodeIds);
        this.childNodeIds[_id]=null;
        this.childNodeIds.splice(idx,1);
        if(this.childNodeIds==null||this.childNodeIds.length==0){
            this.childNodeIds=null;
            this.hasChild=false;
            this.data.children=null;
            delete this.data.children;
            this.txtDom.className='node file';
            this.dom.removeChild(this.innerDom);           
        }else{
            this._removeChildData(val);
        }
	},
	_removeChildData:function(val){
		if(this.data.children==null||this.data.children.length==0){
            return;
        }
		var idx=-1;
		for(var i=0,l=this.data.children.length;i<l;i++){
			if(val==this.data.children[i].val){
				idx=i;
				break;
			}
		}
		if(idx!=-1){
			this.data.children[idx]=null;
			this.data.children.splice(idx,1);
		}		
	},
	clear:function(){
		this.el.unbind('.treeNode');
		this.el.remove();
		for(var p in this){
            if(!p || p == 'clear'){continue;}
            this[p] = null;
            delete this[p];
        }
	}
};
